package easyexcel;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellExtra;

import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ConverterUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 模板的读取类
 *
 * @author Jiaju Zhuang
 */
@Slf4j
public class DemoDataListener implements ReadListener<Map<Integer, String>> {

    /**
     * 正文起始行
     */
    private int headRowNumber;
    /**
     * 数据
     */
    protected List<Map<Integer, String>> dataList = new ArrayList<>();

    public DemoDataListener(int headRowNumber) {
        this.headRowNumber = headRowNumber;
    }

    public List<Map<Integer, String>> getDataList() {
        return dataList;
    }

    public void reset(int headRowNumber) {
        this.headRowNumber = headRowNumber;
        this.dataList.clear();
    }

    public int getHeadRowNumber() {
        return headRowNumber;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        dataList.add(data);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        final int beforeSize = dataList.size();
        // 进行去空
        dataList = dataList.stream()
                .filter(it -> it.values().stream().anyMatch(Objects::nonNull))
                .collect(Collectors.toList());
        log.info("所有数据解析完成，所有行数 = " + beforeSize + ", 有效行数 = " + dataList.size());
    }

    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        if (extra.getType() == CellExtraTypeEnum.MERGE) {
            if (extra.getRowIndex() >= this.headRowNumber) {
                int firstRowIndex = extra.getFirstRowIndex() - headRowNumber;
                int firstColumnIndex = extra.getFirstColumnIndex();
                int lastRowIndex = extra.getLastRowIndex() - headRowNumber;
                int lastColumnIndex = extra.getLastColumnIndex();
                String initValue = getInitValue(firstRowIndex, firstColumnIndex);
                if (initValue != null) {
                    // 设置值
                    for (int i = firstRowIndex; i <= lastRowIndex; i++) {
                        for (int j = firstColumnIndex; j <= lastColumnIndex; j++) {
                            this.dataList.get(i).put(j, String.valueOf(initValue));
                        }
                    }
                }
            }
        }
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.error("table onException 解析失败，但是继续解析下一行");
        // 如果是某一个单元格的转换异常 能获取到具体行号
        // 如果要获取头的信息 配合invokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
        }
        throw exception;
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        Map<Integer, String> integerStringMap = ConverterUtils.convertToStringMap(headMap, context);
        System.out.println("invokeHead" + JsonUtils.toJSONString(integerStringMap));
    }

    private String getInitValue(Integer firstRowIndex, Integer firstColumnIndex) {
        String filedValue = null;
        if (firstRowIndex < dataList.size()) {
            Map<Integer, String> integerStringMap = dataList.get(firstRowIndex);
            for (Map.Entry<Integer, String> entry : integerStringMap.entrySet()) {
                if (entry.getKey().equals(firstColumnIndex)) {
                    filedValue = entry.getValue();
                    break;
                }
            }
        }
        return filedValue;
    }
}